<?php
/**
* md5_file($filename)  计算文件的 MD5 散列
* $file_name:文件的绝对路径
* 如果是同一个文件，返回的散列值是一致的
* 可以用这个办法来判断文件是否上传过
*/
function hashFile($file_name){
    return md5_file($file_name);
}

// 裁切图片
function imageCropper($source_path, $target_width, $target_height, $save_path)
{
    header("Content-type:image/png");
    // 确定图片类型，创建对应的cover对象
    $source_info  = getimagesize($source_path);
    $source_mime  = $source_info['mime'];
    if ($source_mime == 'image/gif') $src_im = imagecreatefromgif($source_path);
    if ($source_mime == 'image/jpeg') $src_im = imagecreatefromjpeg($source_path);
    if ($source_mime == 'image/png') $src_im = imagecreatefrompng($source_path);
    // 创建图片对象
    $dst_im = imagecreatetruecolor($target_width, $target_height);
    imagecopy($dst_im, $src_im, 0, 0, 0, 0, $target_width, $target_height);
    imagepng($dst_im, $save_path);
    imagedestroy($dst_im);
    imagedestroy($src_im);
    // exit;
}
// 图片旋转。$path:图片路径；$angle旋转角度(逆时针旋转)
function imgRevolve($path,$angle=0)
{
    $angle = $angle != 0 ? $angle : 90;
    $img = imagerotate($path,$angle,0);
    // 输出图片
    header('content-type:image/png');
    imagepng($img, $path);
}

// 图片缩放
function imgZoom($path, $save_path, $percent = 0)
{
    // 打开图片来源
    $img = imagecreatefrompng($path);
    // 定义百分比，缩放到0.1大小    
    $percent = ($percent != 0) ? $percent : 0.1;
    list($width, $height) = getimagesize($path);
    // 设置缩放后的宽高
    $new_width = $width * $percent;
    $new_height = $height * $percent;
    $new_image = imagecreatetruecolor($new_width, $new_height);    
    // 将原图$image按照指定的宽高，复制到$new_image指定的宽高大小中
    imagecopyresampled($new_image, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);    
    // 输出图片
    header('content-type:image/png');
    imagepng($new_image, $save_path);
}

// 把两张图片合成一张：居中显示
function imgToOne($path_1, $path_2, $save_url)
{
    //创建图片对象
    $image_1 = imagecreatefrompng($path_1);
    $image_2 = imagecreatefrompng($path_2);
    $img1_w = imagesx($image_1);
    $img1_h = imagesy($image_1);
    $src_w = imagesx($image_2);
    $src_h = imagesy($image_2);
    $dst_x = ($img1_w - $src_w) / 2;
    $dst_y = ($img1_h - $src_h) / 2;
    $src_x = 0;
    $src_y = 0;
    $pct = 100;
    /**
     * 合成图片
     * $image_1:目标图片链接资源
     * $image_2:源图像链接资源
     * $dst_x:目标点的x坐标
     * $dst_y:目标点的y坐标
     * $src_x:在源图上起点的x坐标
     * $src_y:在源图上起点的y坐标
     * $src_w:设置源宽度
     * $src_h:设置源高度
     * $pct:透明度：100不透明，0完全透明
     */
    imagecopymerge($image_1, $image_2, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct);
    // 输出合成图片
    imagepng($image_1, $save_url);
}
//向不同格式的图片中间画一个字符串（也是文字水印）
function imgAddTxt($filename,$string){
    //获取图片的属性，第一个宽度，第二个高度，类型1=>gif，2=>jpeg,3=>png
    list($width,$height,$type) = getimagesize($filename);
    //可以处理的图片类型
    $types = array(1=>"gif",2=>"jpeg",3=>"png",);
    //通过图片类型去组合，可以创建对应图片格式的，创建图片资源的GD库函数
    $createfrom = "imagecreatefrom".$types[$type];
    //通过“变量函数”去打对应的函数去创建图片的资源
    $image = $createfrom($filename);
    //设置居中字体的X轴坐标位置
    $fontSize = 20;
    $font = $_SERVER['DOCUMENT_ROOT'] . "/simsun.ttc"; //字体在服务器上的绝对路径
    $fontBox = imagettfbbox($fontSize, 0, $font, $string);
    $x = ceil(($width - $fontBox[2]) / 2);
    //设置居中字体的Y轴坐标位置
    $y = 420;
    //设置字体的颜色为黑色
    $textcolor = imagecolorallocate($image, 0, 0, 0);
    //向图片画一个指定的字符串
    //imagestring($image, 5, $x, $y, $string, $textcolor);
    imagefttext($image, $fontSize, 0, $x, $y, $textcolor, $font, $string);
    //通过图片类型去组合保存对应格式的图片函数
    $output = "image".$types[$type];
    //通过变量函数去保存对应格式的图片
    $output($image,$filename);
    imagedestroy($image);
}

//把数组整理成树结构
function array_tree($array,$field="id",$pid=0){
    $result = [];
    foreach($array as $key => $value){
        if($value['pid']==$pid){
            $value['children']=array_tree($array,$field,$value[$field]);
            $result[]=$value;
        }
    }
    return $result;
}

// 把一维数组组装成树状结构
function setTree($data,$parent_id=0){
    $result = [];
    foreach($data as $val){
        if($val['parent_id'] == $parent_id){
            $child = setTree($data,$val['id']);
            if($child){
                $val['child'] = $child;
            }
            $result[] = $val;
        }
    }
    return $result ?: false;
}


/**
 * 递归重组数组，按照父子关系顺序排列
 * @param  [type]  $arr   [要重新排序的数组]
 * @param  integer $pid   [父级ID]
 * @param  integer $level [等级]
 * @return [type]         [description]
 */
function getTree($arr,$pid=0,$level = 0,&$lists=[]){
	//声明静态数组,避免递归调用时,多次声明导致数组覆盖
	foreach ($arr as $key => $val) {
		if ($val['pid'] == $pid) {
			$val['level'] = $level;
			//把数组放到list中
			$lists[] = $val;
			//把这个节点从数组中移除,减少后续递归消耗
			unset($arr[$key]);
			//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
            getTree($arr, $val['id'],$level+1,$lists);
		}
	}
	return $lists;
}
/**
 * 把数组组成子父级关系配合 getTree 使用
 * @param  [type] $arr [要重新排列的数组]
 * @return [type]      [description]
 */
function childTree($arr){
	$lists = [];
	$len = count($arr);
	for ($i=0; $i < $len; $i++) {
		if (isset($arr[$i])) {
			$arr[$i]['child'] = [];			
			for ($j=$i+1; $j < $len; $j++) { 
				if ($arr[$j]['pid'] == $arr[$i]['id']) {
					$arr[$i]['child'][] = $arr[$j];
					unset($arr[$j]);
				}
			}
			$lists[] = $arr[$i];
		}
	}
	return $lists;
}
/**
 * 检测是否使用手机访问
 * @access public
 * @return bool
 */
function isMobile(){
	if ($_SERVER['HTTP_VIA'] && stristr($_SERVER['HTTP_VIA'], "wap")) {
		return true;
	} elseif ($_SERVER['HTTP_ACCEPT'] && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
		return true;
	} elseif ($_SERVER['HTTP_X_WAP_PROFILE'] || $_SERVER['HTTP_PROFILE']) {
		return true;
	} elseif ($_SERVER['HTTP_USER_AGENT'] && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
		return true;
	}
	return false;
}
/**
 * 检测是否是微信浏览器
 * @return boolean [description]
 */
function isWechat(){
	if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {
		return true;
	}
	return false;
}
/**
 * 微信生成签名
 * @param  [array] $obj [要生成签名的数据]
 * @param  [type] $key [pay_key]
 * @return [type]      [description]
 */
function getSigns($obj,$key){
	// 签名步骤一：按字典序排序参数
	ksort($obj);
	// 把排好序的拼成字符串
	$String = formatKeyValuePair($obj, false);
	//签名步骤二：在string后加入KEY
	$String = $String . "&key=" . $key;
	//签名步骤三：MD5加密
	$String = md5($String);
	//签名步骤四：所有字符转为大写
	return strtoupper($String);
}
/**
 * 拼接键值对，并用"&"连接起来
 * @param  [array]  $keyValue  [要拼接的数组]
 * @param  boolean $urlencode [是否需要urlencode编码]
 * @return [string]             [description]
 */
function formatKeyValuePair($keyValue, $urlencode = false){
	$buff = '';
	foreach ($keyValue as $k => $v) {
		if($k != "sign" && $v != "" && !is_array($v)){
			if ($urlencode) {
				$v = urldecode($v);
			}
			$buff .= $k . "=" . $v . "&";
		}
	}
	$buff = trim($buff, "&");
	return $buff;
}
/**
 * Xml转数组
 * @param  [xml] $xml [要转换的xml数据]
 * @return [array]      [转换好的数组]
 */
function xmlToArray($xml) {
	if($xml == '') return '';
    //禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
    return json_decode(json_encode($xmlstring), true);
}
/**
 * 数组转xml
 * @param  [array] $arr [要转换的数组]
 * @return [xml]      [转换好的xml]
 */
function arrayToXml($arr) {
    if(!is_array($arr) || count($arr) == 0) return '';
	$xml = "<xml>";
	foreach ($arr as $k => $v){
		if (is_numeric($v)){
			$xml.="<".$k.">".$v."</".$k.">";
		}else{
			$xml.="<".$k."><![CDATA[".$v."]]></".$k.">";
		}
	}
	$xml.="</xml>";
	return $xml;
}
/**
 * 以post方式提交xml到对应的接口url
 *
 * @param string $xml  需要post的xml数据
 * @param string $url  url
 * @param bool $useCert 是否需要证书，默认不需要
 * @param int $second   url执行超时时间，默认30s
 * @throws WxPayException
 */
function postXmlCurl($xml, $url, $second=30, $useCert=false, $sslcert_path='', $sslkey_path=''){
	$ch = curl_init();
	//设置超时
	curl_setopt($ch, CURLOPT_TIMEOUT, $second);
	curl_setopt($ch,CURLOPT_URL, $url);
	//设置header
	curl_setopt($ch, CURLOPT_HEADER, FALSE);
	//要求结果为字符串且输出到屏幕上
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
	curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
	curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
 
	if($useCert == true){
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
		//设置证书
		//使用证书：cert 与 key 分别属于两个.pem文件
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLCERT, $sslcert_path);
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLKEY, $sslkey_path);
	}
	//post提交方式
	curl_setopt($ch, CURLOPT_POST, TRUE);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
	//运行curl
	$data = curl_exec($ch);
	  
	//返回结果
	if($data){
		curl_close($ch);
		return $data;
	} else {
		$error = curl_errno($ch); 
		curl_close($ch);
		return false;
	}
}
function getCurl($url, $second = 3)
{
    $ch = curl_init();
    //设置超时
    curl_setopt($ch, CURLOPT_TIMEOUT, $second);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
    //设置header
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    //post提交方式
    //curl_setopt($ch, CURLOPT_POST, TRUE);
    //curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
    curl_setopt($ch, CURLOPT_TIMEOUT, 40);
    //set_time_limit(10);
    //运行curl
    $data = curl_exec($ch);
    //返回结果
    if ($data) {
        curl_close($ch);
        return $data;
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        return "";
        //return "网络出错，错误码:$error";
    }
}

/*
*  php访问url路径，get请求
*/
function curl_get($url){
    // 初始化
    $curl = curl_init();
    // 设置url路径
    curl_setopt($curl, CURLOPT_URL, $url);
    // 将 curl_exec()获取的信息以文件流的形式返回，而不是直接输出。
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    // CURLINFO_HEADER_OUT选项可以拿到请求头信息
    curl_setopt($curl, CURLINFO_HEADER_OUT, true);
    // 不验证SSL
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    // 执行
    $data = curl_exec($curl);
    // 打印请求头信息
    // echo curl_getinfo($curl, CURLINFO_HEADER_OUT);
    // 关闭连接
    curl_close($curl);
    // 返回数据
    return $data;
}

function postCurl($url,$data){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json; charset=utf-8','Content-Length: ' . strlen($data)));
    ob_start();
    curl_exec($ch);
    $return_content = ob_get_contents();
    ob_end_clean();
    $return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    return array($return_code, $return_content);
}

//请求数据到短信接口，检查环境是否 开启 curl init。
function curlPost($curlPost,$url){
	$curl = curl_init();
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_HEADER, false);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_NOBODY, true);
	curl_setopt($curl, CURLOPT_POST, true);
	curl_setopt($curl, CURLOPT_POSTFIELDS, $curlPost);
	$return_str = curl_exec($curl);
	curl_close($curl);
	return $return_str;
}

// 发送POST请求
function curl_post($url, $data=array()){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    // POST数据
    curl_setopt($ch, CURLOPT_POST, 1);
    // 把post的变量加上
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $output = curl_exec($ch);
    curl_close($ch);
    return $output;
}

/**
 * post请求，支持https
 * @param  [type] $url  [提交的地址]
 * @param  [type] $data [提交的数据]
 * @return [type]       [description]
 */
function curl_post($url,$data){ // 模拟提交数据函数
	$curl = curl_init(); // 启动一个CURL会话
	curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中不检查SSL加密算法是否存在
	curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
	curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
	curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
	curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
	curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
	curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
	$tmpInfo = curl_exec($curl); // 执行操作
	if (curl_errno($curl)) {
		echo 'Errno'.curl_error($curl);//捕抓异常
	}
	curl_close($curl); // 关闭CURL会话
	return $tmpInfo; // 返回数据，json格式
}
/**
 * 把秒数变为 00：00:00
 * @param [type] $s [秒数]
 */
function setSecond($s){
	$str = '';
	$h = floor($s / 3600);
	$i = floor(($s - $h * 3600) / 60);
	$ls = $s - ($h * 3600) - ($i * 60) ;
	if ($h > 9) {
		$h = (string)$h;
	}else{
		$h = '0'.(string)$h;
	}
	if ($i > 9) {
		$i = (string)$i;
	}else{
		$i = '0'.(string)$i;
	}
	if ($ls > 9) {
		$ls = (string)$ls;
	}else{
		$ls = '0'.(string)$ls;
	}
	return $h.':'. $i .':'.$ls;
}
/**
 * 将秒数格式为 *小时*分钟*秒
 * @param [type] $second [秒数]
 */
function formatSecond($second){
	$str = '';
	// 小时数
	$H = floor($second / 3600);
	// 分钟数
	$i = floor(($second - $H*3600)/60);
	// 剩余秒数
	$s = $second - ($H * 3600) - ($i * 60);

	if ($H > 0) {
		$str .= $H.'小时';
	}
	if ($i > 0) {
		$str .= $i.'分钟';
	}
	$str .= $s.'秒';
	return $str;
}


/**
 * 图片转换为 base64格式编码
 * @param  [type] $image_file [图片路径]
 * @return [type]             [description]
 */
function base64EncodeImage($image_file) {
	$base64_image = '';
	$image_info = getimagesize($image_file);
	$image_data = fread(fopen($image_file, 'r'), filesize($image_file));
	$base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data));
	return $base64_image;
}
// base64上传图片:TP6
function uploadBase64($base64img)
{
    $result = explode(',',$base64img);
    // 分割
    if (preg_match('/^(data:\s*image\/(\w+);base64)/',$result[0],$info)) {
        $pic = base64_decode($result[1]);
        if (!$pic) {
            exit('解码失败');
        }
        $url = '/storage/' . date('Ymd', time());
        $new_file = app()->getRootPath() . '/public' . $url;
        if (!file_exists($new_file)) {
            // 检查是否存在文件夹，不存在则创建
            mkdir($new_file, 0777);
        }
        $pic_name = md5(uniqid() . time()) . '.' . $info[2];
        if (file_put_contents($new_file . '/' . $pic_name, $pic)) {
            return ['file_path'=> 'https://shouyin.zhilongyihuo.com' . $url . '/' . $pic_name];
        }
    }
    exit('不是base64格式');
}

// BASE64上传图片
public function uploadImageBase(){
	$picpath = $this->request->post('image');
	if (empty($picpath)) {
		return jsonx(201,'缺少参数',null);
	}
    // post方式接收的数据, 加号会被替换为空格, 需要重新替换回来, 若不是post数据, 不需要执行
    $base64_image = str_replace(' ', '+', $picpath);        
    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image, $result)){
        //定义图片储存文件目录
        $file_path = 'api/'.date('Ymd');
        $dir = WEB_ROOT.'upload/' . $file_path;
        //定义文件名称
        $picname = date("his") . rand(10000, 99999);
        if (!is_dir($dir)){
            //如果不存在就创建该目录
            mkdir($dir,0777,true);
        }
        //获取图片后缀
        $picdir=$picname.'.'.$result[2];
        //图片名称
        $image_url = $dir.'/'.$picdir;
        // 保存图片
        if (file_put_contents($image_url, base64_decode(str_replace($result[1], '', $base64_image)))) {
        	$imagepath = saveFile($picdir,$file_path .'/'. $picdir);
        	$filepath = 'http://' . $_SERVER['HTTP_HOST'] . '/upload/' . $imagepath;
        	return jsonx(200,'上传成功！',['imagepath'=>$imagepath,'filepath'=>$filepath]);
        }else{
        	return jsonx(201,'上传失败！',null);
        }
    }else{
    	return jsonx(201,'格式错误',null);
    }
}

// 下载文件,文件流形式
public function downloadfile(){
	// 要下载的文件地址
	$url = $this->request->param('url');
	if (empty($url)) {
		return jsonx(201,'缺少参数',null);
	}
	// 原文件名称
	$new_name = Db::name('asset')->where('file_path',$url)->value('filename');
	if (!$new_name) {
		// 如果没有原文件名称,以时间戳作为新文件名称
		$new_name = time() . '.' . getExtension($url);
	}
	// 保存在服务器上的路径
	$save_url = str_replace('http://' . $_SERVER['HTTP_HOST'] , $_SERVER['DOCUMENT_ROOT'], cmf_get_image_url($url));
	return filedownload($new_name,$save_url);
}
/**
 * 获取文件后缀
 * @param  [string] $filename [文件名称，带后缀]
 * @return [string]           [文件后缀]
 */
function getExtension($filename){
	$exploded = explode(".", $filename);
	return $exploded[count($exploded) - 1];
}
/**
 * 生成随机字符串(字母+数字)
 * @param  [int] $lenth [字符串长度]
 * @return [str]        返回随机指定长度随机字符串
 * @param integer $lenth [description]
 */
function setToken($lenth = 20){
	$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.time();
	$str = '';
	for ($i = 0; $i < $lenth; $i++) {
		$str .= $chars[mt_rand(0, strlen($chars) - 1)];
	}
	return $str;
}
// 生成随机字符串(数字)
function setCode($lenth = 6){
	$chars = '0123456789';
	$str = '';
	for ($i = 0; $i < $lenth; $i++) {
		$str .= $chars[mt_rand(0, strlen($chars) - 1)];
	}
	return $str;
}

/**
 * 转为json字符串输出
 * @param  [type] $code [代码]
 * @param  [type] $msg  [信息]
 * @param  [type] $data [数组]
 * @return [type]       [description]
 */
function jsonx($code,$msg,$data){
	return json(['code'=>$code,'msg'=>$msg,'data'=>$data]);
}


/**
 * 接收上传的文件，查询是否文件已上传过
 * @param  [object] $file [接收到的文件对象]
 * @return [string]       [新上传的文件，返回文件地址；已上传过的文件返回老地址]
 */
function haveFile($file){
	// 上传文件名称
	$filename = $file->getInfo('name');
	
	// 移动到框架应用根目录/upload/api/ 目录下
	$info = $file->move(WEB_ROOT.'upload/api/');
	if($info){
		// 要保存的路径，并且把 '\' 转为 '/'
		$saveName = 'api/' . str_replace('\\', '/', $info->getSaveName());
		unset($info);
		$file_path = saveFile($filename,$saveName);
		return ['code'=>200,'filepath'=>$file_path];
	}else{
		// 上传失败获取错误信息
		return ['code'=>201,'msg'=>$file->getError()];
	}
}
/**
 * 返回保存的文件路径
 * @param  [type] $filename [文件名称]
 * @param  [type] $saveName [保存的文件路径]
 * @return [type]           [description]
 */
function saveFile($filename,$saveName){
	// 文件所在服务器的路径
	$uploadPath = WEB_ROOT . 'upload/';
	$strSaveFilePath = $uploadPath . $saveName;

	$arrInfo["user_id"]     = 0;
	$arrInfo["file_size"]   = filesize($strSaveFilePath);
	$arrInfo["create_time"] = time();
	$arrInfo["file_md5"]    = md5_file($strSaveFilePath);
	$arrInfo["file_sha1"]   = sha1_file($strSaveFilePath);
	$arrInfo["file_key"]    = $arrInfo["file_md5"] . md5($arrInfo["file_sha1"]);
	$arrInfo["filename"]    = $filename;
	$arrInfo["file_path"]   = $saveName;
	$arrInfo["suffix"]      = getExtension($filename);

	if ($objAsset = Db::name('asset')->where([['user_id','=',$arrInfo['user_id']],['file_key','=',$arrInfo['file_key']]])->find()) {
		// 如果文件已经存在，删除后上传的文件，返回早上传的文件地址
		$arrInfo["file_path"] = $objAsset["file_path"];			
		@unlink($strSaveFilePath); // 删除已经上传的文件
	}else{
		// 如果不存在，保存文件记录
		Db::name('asset')->insert($arrInfo,true);
	}
	return $arrInfo['file_path'];
}

/**
 * 生成原始的二维码(生成图片文件)
 * @param  string $url [要生成二维码的信息]
 * @param  integer $type [是直接输出还是保存二维码:1保存二维码，返回保存路径；2直接输出二维码]
 * @param  integer $matrixPointSize [生成图片大小]
 * @return [type]      [保存二维码的相对位置]
 */
function scerweima($url='',$type=1,$logo='',$matrixPointSize=0,$filename=''){
	require_once CMF_ROOT.'extend/phpqrcode.php';
	$value = $url;         //二维码内容
	$errorCorrectionLevel = 'L';  //容错级别
	if (empty($matrixPointSize)) {
		$matrixPointSize = 10;      //生成图片大小
	}
	if ($type == 1) {
		//生成二维码图片
		if (empty($filename)) {
			$filename = date('Ymd').setToken(9).'.png';
		}else{
			$filename = $filename.'.png';
		}
		$filepath = 'qrcode/'.date('Ymd').'';
		$fileurl = WEB_ROOT.'upload/'.$filepath;
		if (!is_dir($fileurl)) {
			mkdir($fileurl,0777,true);
		}
		// 保存二维码
		QRcode::png($value, $fileurl .'/'. $filename , $errorCorrectionLevel, $matrixPointSize, 2);
		// 返回保存的相对路径
		return $filepath .'/'. $filename;
	}
	if ($type == 2) {
		// 直接输出二维码
		echo QRcode::png($value,false , $errorCorrectionLevel, $matrixPointSize, 2);
		die;
	}
	if ($type == 3) {
		//生成带LOGO的二维码图片
		if (empty($filename)) {
			$file_name = date('Ymd').setToken(9);
		}else{
			$file_name = $filename;
		}
		$filename = $file_name.'.png';
		$dirname = date('Ymd');	
		$fileurl = WEB_ROOT.'upload/qrcode/'.$dirname;
		$logo_url = 'logo/'.$dirname;
		$logourl = WEB_ROOT.'upload/'.$logo_url;
		if (!is_dir($fileurl)) {
			mkdir($fileurl,0777,true);
		}
		if (!is_dir($logourl)) {
			mkdir($logourl,0777,true);
		}
		//生成一个二维码图片  
		QRcode::png($url, $fileurl .'/'. $filename, $errorCorrectionLevel, $matrixPointSize, 2);
		//已经生成的原始二维码图,也在根目录下  
		$qrcode = $fileurl .'/'. $filename;  
		//logo图片存在  
		if ($logo !== FALSE) {  
			$qrcode = imagecreatefromstring(file_get_contents($qrcode));  
			$logo = imagecreatefromstring(file_get_contents($logo));  
			$qrcode_width = imagesx($qrcode);   //二维码图片宽度  
			$qrcode_height = imagesy($qrcode);  //二维码图片高度  
			$logo_width = imagesx($logo);       //logo图片宽度  
			$logo_height = imagesy($logo);      //logo图片高度  
			$logo_qr_width = $qrcode_width / 5;  
			$scale = $logo_width / $logo_qr_width;  
			$logo_qr_height = $logo_height / $scale;  
			$from_width = ($qrcode_width - $logo_qr_width) / 2;  
			//重新组合图片并调整大小  
			imagecopyresampled($qrcode, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);  
		}  
		//输出图片
		$logo_url = $logo_url.'/'.$file_name.'.png';
		imagepng($qrcode, 'upload/'.$logo_url);
		return $logo_url;
	}
}

/**
 * 求两个已知经纬度之间的距离,单位为米
 * 
 * @param lng1 $ ,lng2 经度
 * @param lat1 $ ,lat2 纬度
 * @return float 距离，单位米
 * @author www.Alixixi.com 
 */
function getdistance($lng1, $lat1, $lng2, $lat2) {
	// 地球半径(单位：千米)
	$r = 6378.137; 
    // 将角度转为狐度
    $radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
    $radLat2 = deg2rad($lat2);
    $radLng1 = deg2rad($lng1);
    $radLng2 = deg2rad($lng2);
    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;
    $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
    // 计算距离，并换算成米
    $s = $s * $r * 1000;
    return $s;
}

// 流形式下载文件
function filedownload($filename,$url){
	if(!file_exists($url)){
		echo "文件不存在";
	}
	$fp=fopen($url,"r");
	$filesize=filesize($url);
	header("Content-type: application/octet-stream");
	header("Accept-Ranges: bytes");
	header("Accept-Length: $filesize");
	header("Content-Disposition: attachment; filename=".$filename);
	ob_clean();
	flush();
	$buffer=1024;
	$count=0;
	while(!feof($fp)&&($filesize-$count>0)){
		$data=fread($fp,$buffer);
		$count+=$data;
		echo $data;
	}
	fclose($fp);
}

/**
 * 伪文件流的方式下载文件
 * @param  [type] $filename     [文件名称，带后缀]
 * @param  [type] $path         [文件保存的地址]
 * @param  string $content_type [二进制流，不知道文件类型]
 * @return [type]               [description]
 */
function filedownload1($filename,$path,$content_type='application/octet-stream'){
    ob_clean();
    header('Pragma: public');
    header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
    header('Cache-Control: no-store, max-age=0, no-cache, must-revalidate'); // HTTP/1.1
    header('Cache-Control: post-check=0, pre-check=0', false);
    header('Cache-Control: private');
    header('Content-Transfer-Encoding: none'); 
    header('Content-Disposition: attachment; filename='.$filename.'');
    header('Content-Type: '.$content_type.'; name="'.$filename.'"');
    echo file_get_contents($path);
    exit;
}

/**
 * 微信网页授权，获取微信信息
 * 方法1
 */
function get_user_wechat()
{
	$appid = "";
	$secretKey = "";
    $request = request();
    $curUrl = $request->domain() . $request->url();
    if (!$request->param('code/s')) {
    	// 1.引导用户进入授权页面同意授权，获取code
        $apiUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$curUrl}&response_type=code&scope=snsapi_userinfo&state=test#wechat_redirect";
        header("Location:{$apiUrl}");
        exit;
    } else {
    	// 2.通过code换取网页授权access_token
        $code = $request->param('code/s');
        $apiUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secretKey}&code={$code}&grant_type=authorization_code";
        try {
            $res = file_get_contents($apiUrl);
            $wxBack = json_decode($res, true);
        } catch (\Exception $exception) {
            return false;
        }
        // 3.通过网页授权access_token和openid获取用户基本信息
        $scope_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$wxBack['access_token']."&openid=".$wxBack['openid']."&lang=zh_CN";
        try {
            $info = file_get_contents($scope_url);
            $wechat = json_decode($info, true);
        } catch (\Exception $exception) {
            return false;
        }
        return $wechat;
    }
}

/**
 * 方法2：
 */
function wxconfig(){
	$weixin = [
		// 公众号appid
		"appid" => "",
		// 微信secret
		"secret" => "",
	];
	return $weixin;
}

/**
 * 1.用户同意授权，获取code
 * code只能使用一次，5分钟未被使用自动过期。
 * @param  string $redirect [授权后重定向的回调链接地址， 请使用 urlEncode 对链接进行处理]
 * @return [url]            [获取code的地址]
 */
function getCode($redirect=''){
    $weixin = wxconfig();
    $appid = $weixin['appid'];
    if (empty($redirect)) {
        $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
        $redirect = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
    }
    $state = "123";
    // snsapi_base不弹出授权窗口，只能获取openid，snsapi_userinfo弹出授权窗口，可以获取昵称等信息。
    $snsapi = "snsapi_userinfo";
    $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$redirect}&response_type=code&scope={$snsapi}&state={$state}#wechat_redirect";
    return $url;
}
/**
 * 2.通过code换取网页授权access_token
 * access_token有效时长7200秒
 * 过期可以用refresh_token刷新
 * refresh_token有效期30天
 * @param  [string] $code [code值]
 * @return [type]       [description]
 */
function getUserToken($code){    
    $weixin = wxconfig();
    $appid = $weixin['appid'];
    $secret = $weixin['secret'];
    $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
    $userinfo = getCurl($url, 60);
    // 对JSON格式的字符串进行编码
    return json_decode($userinfo,true);
}
/**
 * 3.刷新access_token(如果需要)
 * @param  [type] $refresh_token [第2步获取到的refresh_token]
 * @return [type]                [description]
 */
function refreshToken($refresh_token){
	$weixin = wxconfig();
    $appid = $weixin['appid'];
	$url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={$appid}&grant_type=refresh_token&refresh_token={$refresh_token}";
	$userinfo = getCurl($url, 60);
    // 对JSON格式的字符串进行编码
    return json_decode($userinfo,true);
}
/**
 * 4.拉取用户信息
 * @param  [type] $openid       [description]
 * @param  [type] $access_token [description]
 * @return [type]               [description]
 */
function getInfo($openid,$access_token){
	$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN";
	$userinfo = getCurl($url, 60);
    // 对JSON格式的字符串进行编码
    return json_decode($userinfo,true);
}
/**
 * 查询access_token和jsapi_ticket
 * access_token : access_token
 * jsapi_ticket : ticket
 */
function findAccessToken($field='access_token'){
    $file_url=$_SERVER['DOCUMENT_ROOT'].'/'.$field.'.txt';
    // 从本地读取
    $file_content = getFileContent($file_url);
    $functionName = "get_".$field;
    if (empty($file_content)) {
        return $functionName($file_url);
    }
    $file_content = json_decode($file_content,true);
    if ($file_content['expires_in'] <= time()) {
        return $functionName($file_url);
    }else{
        return $file_content[$field];
    }
}
function get_ticket($file_url){
    $access_token = findAccessToken();
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=".$access_token."&type=jsapi";
    return getWchatData($url,'ticket',$file_url);
}
// 从微信服务器获取access_token,并写入本地
function get_access_token($file_url){
    $appid = "";
    $secret = "";
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;
    return getWchatData($url,'access_token',$file_url);
}
// 记录从微信服务器获取到的内容
function getWchatData($url,$field,$file_url){
    $res = file_get_contents($url);
    $wxBack = json_decode($res, true);
    if (isset($wxBack['errcode']) && ($wxBack['errcode'] != 0)) {
        exit($res);
    }else{
        // 写入文档
        $wxBack['expires_in'] += time();
        $res = json_encode($wxBack);
        writeFile($file_url,$res);
        return $wxBack[$field];
    }
}
// 读取文件内容
function getFileContent($file_url){
    if(!file_exists($file_url)){
        return "";
    }
    $myfile = fopen($file_url, "r") or die("Unable to open file!");
    $filesize = filesize($file_url);
    if($filesize == 0){
        return "";
    }
    $content = fread($myfile,$filesize);
    fclose($myfile);
    return $content;
}
// 把内容写入文件
function writeFile($file_url,$txt,$mode="w"){
    $myfile = fopen($file_url, $mode) or die("Unable to open file!");
    fwrite($myfile, $txt);
    fclose($myfile);
}


/**
 * 根据音频文件地址，获取音频时长
 * @param  [type] $path [音频地址(本地相对于硬盘的绝对路径)]
 * @return [type]       [返回音频时长]
 */
function getDuration($path){
	require_once CMF_ROOT.'extend/getid3/getid3.php';
	// 实例化类
	$getID3 = new getID3();
	// 分析文件，$path为音频文件的地址
	$ThisFileInfo = $getID3->analyze($path);
	// 这个获得的便是音频文件的时长
	return $ThisFileInfo['playtime_seconds'];
}


/**
 * ThinkPHP5 查询时间范围时 设置查询时间
 * @param datetime $start_time [开始时间:2019-06-01]
 * @param datetime $end_time   [结束时间]
 * @param string $field      [查询的字段：默认为'add_time']
 * @return  array [code:200,成功；201失败。data:成功返回的数组；msg:失败的提示信息]
 */
function setBetweenTime($start_time='',$end_time='',$field='add_time'){
	if (trim($start_time)) {
		$start = strtotime($start_time);
		if (trim($end_time)) {
			$end = strtotime($end_time);
			if ($end < $start) {
				// 结束时间小于开始时间
				// $this->error('结束时间不能小于开始时间');
				return ['code'=>201,'msg'=>'结束时间不能小于开始时间'];
			}
			if ($end > $start) {
				// 结束时间大于开始时间
				return ['code'=>200,'data'=>[$field,'between time',[$start_time,$end_time]]];
			}
			if ($end == $start) {
				// 结束时间等于开始时间，查询某一天
				$end = date("Y-m-d", strtotime($end_time."+1 day"));
				return ['code'=>200,'data'=>[$field,'between time',[$start_time,$end]]];
			}
		}else{
			// 只有开始时间
			return ['code'=>200,'data'=>[$field,'>= time',$start_time]];

		}
	}else{
		// 只有结束时间
		if (trim($end_time)) {
			// 计算下一天的日期
        	$end = date("Y-m-d", strtotime($end_time."+1 day"));
        	// 小于某个时间
			return ['code'=>200,'data'=>[$field,'<= time',$end]];
		}
	}
}

function getRealIp(){
    $ip=false;
    if(!empty($_SERVER["HTTP_CLIENT_IP"])){
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode (", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) { array_unshift($ips, $ip); $ip = FALSE; }
        for ($i = 0, $len = count($ips); $i < $len; $i++) {
            if (!eregi ("^(10│172.16│192.168).", $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}

function fileWrite($filename,$str){
    $file = fopen($filename,"w+");
    fwrite($file, $str);
    fclose($file);
}

function fileRead($filename){
    $myfile = fopen($filename, "r") or die("Unable to open file!");
    $content = fread($myfile,filesize($filename));
    fclose($myfile);
    return $content;
}

/**
 * 设置txt配置文件
 * 保存的文件样式：
 * {"abc":"测试156","sex":"男"}
 * @param  [type] $file [文件路径]
 * @param  [type] $key  [key值]
 * @param  [type] $val  [value值]
 */
function upFile($file,$key,$val){
	$config = file_get_contents($file);
	$arr = json_decode($config,true);
	foreach ($arr as $k => $v) {
		if ($k == $key) {
			$arr[$k] = $val;
		}
	}
	$str = json_encode($arr,JSON_UNESCAPED_UNICODE);
	// 写入
	$myfile = fopen($file, "w") or die("Unable to open file!");
	fwrite($myfile, $str);
	fclose($myfile);
}

/**
 * 设置PHP配置文件的值
 * 配置文件为一维数组
 * 保存的文件样式:
 * <?php return ['name'=>'秦晓苏','sex'=>'男','hight'=>178];
 * @param  [type] $file [文件路径]
 * @param  [type] $key  [key值]
 * @param  [type] $val  [value值]
 */
function upConfigOne($file,$key,$val){
	if (is_file($file)) {
		$arr = include($file);
		foreach ($arr as $k => $v) {
			if ($k == $key) {
				if (is_string($v)) {
					$pattern = $v;
				}
				if (is_array($v)) {
					
				}
			}
		}
		$config = file_get_contents($file);
		$config = preg_replace('/'.$pattern.'/', $val, $config);
		// 写入
		$myfile = fopen($file, "w") or die("Unable to open file!");
		fwrite($myfile, $config);
		fclose($myfile);
	}
}
/**
 * 合成群头像图片
 * @param array  $pic_list [图片列表数组]
 * @param boolean $is_save  [是否保存，true保存，false输出到浏览器]
 * @param string $save_path [保存路径]
 * @return boolean|string
 */
function getGroupAvatar($pic_list=array(),$is_save=false,$save_path=''){
	if(empty($pic_list) || empty($save_path)){
		return false;
	}
	if($is_save){
		if(empty($save_path)){
			return false;
		}
	}
	// 只操作前9个图片
	$pic_list = array_slice($pic_list, 0, 9);
	//设置背景图片宽高
	$bg_w = 150; // 背景图片宽度
	$bg_h = 150; // 背景图片高度
	//新建一个真彩色图像作为背景
	$background = imagecreatetruecolor($bg_w,$bg_h);
	//为真彩色画布创建白灰色背景，再设置为透明
	$color = imagecolorallocate($background, 202, 201, 201);
	imagefill($background, 0, 0, $color);
	imageColorTransparent($background, $color);
	//根据图片个数设置图片位置
	$pic_count = count($pic_list);
	$lineArr = array();//需要换行的位置
	$space_x = 3;
	$space_y = 3;
	$line_x = 0;
	switch($pic_count) {
	case 1: // 正中间
		$start_x = intval($bg_w/4); // 开始位置X
		$start_y = intval($bg_h/4); // 开始位置Y
		$pic_w = intval($bg_w/2); // 宽度
		$pic_h = intval($bg_h/2); // 高度
		break;
	case 2: // 中间位置并排
		$start_x = 2;
		$start_y = intval($bg_h/4) + 3;
		$pic_w = intval($bg_w/2) - 5;
		$pic_h = intval($bg_h/2) - 5;
		$space_x = 5;
		break;
	case 3:
		$start_x = 40; // 开始位置X
		$start_y = 5; // 开始位置Y
		$pic_w = intval($bg_w/2) - 5; // 宽度
		$pic_h = intval($bg_h/2) - 5; // 高度
		$lineArr = array(2);
		$line_x = 4;
		break;
	case 4:
		$start_x = 4; // 开始位置X
		$start_y = 5; // 开始位置Y
		$pic_w = intval($bg_w/2) - 5; // 宽度
		$pic_h = intval($bg_h/2) - 5; // 高度
		$lineArr = array(3);
		$line_x = 4;
		break;
	case 5:
		$start_x = 30; // 开始位置X
		$start_y = 30; // 开始位置Y
		$pic_w = intval($bg_w/3) - 5; // 宽度
		$pic_h = intval($bg_h/3) - 5; // 高度
		$lineArr = array(3);
		$line_x = 5;
		break;
	case 6:
		$start_x = 5; // 开始位置X
		$start_y = 30; // 开始位置Y
		$pic_w = intval($bg_w/3) - 5; // 宽度
		$pic_h = intval($bg_h/3) - 5; // 高度
		$lineArr = array(4);
		$line_x = 5;
		break;
	case 7:
		$start_x = 53; // 开始位置X
		$start_y = 5; // 开始位置Y
		$pic_w = intval($bg_w/3) - 5; // 宽度
		$pic_h = intval($bg_h/3) - 5; // 高度
		$lineArr = array(2,5);
		$line_x = 5;
		break;
	case 8:
		$start_x = 30; // 开始位置X
		$start_y = 5; // 开始位置Y
		$pic_w = intval($bg_w/3) - 5; // 宽度
		$pic_h = intval($bg_h/3) - 5; // 高度
		$lineArr = array(3,6);
		$line_x = 5;
	break;
	case 9:
		$start_x = 5; // 开始位置X
		$start_y = 5; // 开始位置Y
		$pic_w = intval($bg_w/3) - 5; // 宽度
		$pic_h = intval($bg_h/3) - 5; // 高度
		$lineArr = array(4,7);
		$line_x = 5;
		break;
	}
	foreach( $pic_list as $k=>$pic_path ) {
		$kk = $k + 1;
		if ( in_array($kk, $lineArr) ) {
			$start_x = $line_x;
			$start_y = $start_y + $pic_h + $space_y;
		}
		//获取图片文件扩展类型和mime类型，判断是否是正常图片文件
		//非正常图片文件，相应位置空着，跳过处理
		$image_mime_info = @getimagesize($pic_path);
		if($image_mime_info && !empty($image_mime_info['mime'])){
			$mime_arr = explode('/',$image_mime_info['mime']);
			if(is_array($mime_arr) && $mime_arr[0] == 'image' && !empty($mime_arr[1])){
				switch($mime_arr[1]) {
					case 'jpg':
					case 'jpeg':
					$imagecreatefromjpeg = 'imagecreatefromjpeg';
					break;
					case 'png':
					$imagecreatefromjpeg = 'imagecreatefrompng';
					break;
					case 'gif':
					default:
					$imagecreatefromjpeg = 'imagecreatefromstring';
					$pic_path = file_get_contents($pic_path);
					break;
				}
				//创建一个新图像
				$resource = $imagecreatefromjpeg($pic_path);
				//将图像中的一块矩形区域拷贝到另一个背景图像中
				// $start_x,$start_y 放置在背景中的起始位置
				// 0,0 裁剪的源头像的起点位置
				// $pic_w,$pic_h copy后的高度和宽度
				imagecopyresized($background,$resource,$start_x,$start_y,0,0,$pic_w,$pic_h,imagesx($resource),imagesy($resource));
			}
		}
		// 最后两个参数为原始图片宽度和高度，倒数两个参数为copy时的图片宽度和高度
		$start_x = $start_x + $pic_w + $space_x;
	}
	if($is_save){
		$dir = pathinfo($save_path,PATHINFO_DIRNAME);
		if(!is_dir($dir)){
			$file_create_res = mkdir($dir,0777,true);
			if(!$file_create_res){
				return false;
			}
		}
		$res = imagejpeg($background,$save_path);
		imagedestroy($background);
		if($res){
			return true;
		}else{
			return false;
		}
	}else{
		//直接输出
		header("Content-type: image/jpg");
		imagejpeg($background);
		imagedestroy($background);
	}
}

/**
* 计算文件大小
*/
function FileSizeConvert($bytes){
    $bytes = floatval($bytes);
    $arrBytes = [
    	["unit"=>"TB", "val"=>pow(1024, 4)],
    	["unit"=>"GB", "val"=>pow(1024, 3)],
    	["unit"=>"MB", "val"=>pow(1024, 2)],
    	["unit"=>"KB", "val"=>1024],
    	["unit"=>"B", "val"=>1],
    ];

    foreach($arrBytes as $val){
        if($bytes >= $val["val"]){
            $result = $bytes / $val["val"];
            $result = round($result, 2) . " " . $val["unit"];
            break;
        }
    }
    return $result;
}